#include "GlobalMessageModel.h"

#include <algorithm>
#include <execution>

GlobalMessageModel::GlobalMessageModel(int max_n_items)
    : MAX_N_ITEMS(max_n_items)
{
    _items.reserve(max_n_items);
}

int GlobalMessageModel::rowCount(const QModelIndex & /*parent*/) const
{
    return _items.count();
}

QVariant GlobalMessageModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || _items.count() <= index.row())
    {
        return {};
    }

    switch (role)
    {
    case Qt::DisplayRole:
        return _items.at(index.row()).text;

    case Qt::DecorationRole:
        switch (_items.at(index.row()).severity)
        {
        case shell::MessageSeverity::Debug:
            return _palette.icons.debug;
        case shell::MessageSeverity::Warning:
            return _palette.icons.warning;
        case shell::MessageSeverity::Error:
            return _palette.icons.error;
        default:
            return _palette.icons.info;
        }

    case Qt::ForegroundRole:
        switch (_items.at(index.row()).severity)
        {
        case shell::MessageSeverity::Debug:
            return QBrush(_palette.foregrounds.debug);
        case shell::MessageSeverity::Warning:
            return QBrush(_palette.foregrounds.warning);
        case shell::MessageSeverity::Error:
            return QBrush(_palette.foregrounds.error);
        default:
            return QBrush(_palette.foregrounds.info);
        }

    default:
        return {};
    }
}

void GlobalMessageModel::append(const QList<GlobalMessageModel::Item> & messages)
{
    if (messages.empty())
    {
        return;
    }

    if (MAX_N_ITEMS <= messages.count())
    {
        _items.clear();
        std::copy( messages.end() - MAX_N_ITEMS
                    , messages.end()
                    , std::back_inserter(_items)
                    );
        emit dataChanged(index(0), index(messages.count()));
        return;
    }

    const int N_MESSAGES_TO_REMOVE = _items.count() + messages.count() - MAX_N_ITEMS;
    if (0 < N_MESSAGES_TO_REMOVE)
    {
        _items.erase(_items.begin(), _items.begin() + N_MESSAGES_TO_REMOVE);
    }

    const int NEW_COUNT = _items.count() + messages.count();
    if (N_MESSAGES_TO_REMOVE < 1)
    {
        beginInsertRows({}, _items.count(), NEW_COUNT - 1);
    }
    _items.append(messages);
    if (N_MESSAGES_TO_REMOVE < 1)
    {
        endInsertRows();
    }
    else
    {
        emit dataChanged(index(0), index(messages.count()));
    }
}

void GlobalMessageModel::setPalette(const GlobalMessageModel::Palette & palette)
{
    beginResetModel();
    _palette = palette;
    endResetModel();
}
